package cn.com.anysdk.redis.impl;

import cn.com.anysdk.redis.config.RedisConfigProperties;
import cn.com.anysdk.redis.event.RedisEventManager;
import cn.com.anysdk.redis.exception.RedisCommandException;
import cn.com.anysdk.redis.exception.RedisException;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.*;

import jakarta.annotation.PreDestroy;
import java.util.*;
import java.util.function.Function;

/**
 * 阿里云Redis服务实现类
 * 支持标准版、集群版、哨兵模式
 */
@Slf4j
public class AliyunRedisServiceImpl extends AbstractRedisServiceImpl {

    private JedisCluster jedisCluster;
    private boolean isClusterMode = false;

    /**
     * 构造函数
     * @param redisProperties Redis配置属性
     * @param eventManager 事件管理器
     */
    public AliyunRedisServiceImpl(RedisConfigProperties redisProperties, RedisEventManager eventManager) {
        super(redisProperties, eventManager);
    }

    @Override
    protected void onInit() {
        checkClusterMode();
        log.info("阿里云Redis服务初始化完成，模式: {}", isClusterMode ? "集群" : "标准");
    }

    @Override
    protected String getServiceName() {
        return "阿里云";
    }

    /**
     * 检查是否为集群模式
     */
    private void checkClusterMode() {
        if (redisProperties.getAliyun() != null &&
            "CLUSTER".equalsIgnoreCase(redisProperties.getAliyun().getMode())) {
            isClusterMode = true;
            try {
                jedisCluster = connectionFactory.getClusterConnection();
                log.info("阿里云Redis集群连接建立成功");
            } catch (Exception e) {
                log.error("获取阿里云Redis集群连接失败", e);
                isClusterMode = false;
            }
        } else {
            isClusterMode = false;
            jedisCluster = null;
            log.info("使用阿里云Redis标准模式");
        }
    }

    /**
     * 重写getJedis以处理集群模式
     */
    @Override
    protected Jedis getJedis() {
        if (isClusterMode) {
            throw new RedisCommandException("阿里云集群模式下不支持获取单个Jedis连接");
        }
        return super.getJedis();
    }

    /**
     * 执行集群模式下的Redis命令并处理异常
     */
    private <T> T executeClusterCommand(Function<JedisCluster, T> operation) {
        if (!isClusterMode || jedisCluster == null) {
            throw new RedisCommandException("当前不是阿里云集群模式或集群连接未初始化");
        }

        try {
            return operation.apply(jedisCluster);
        } catch (Exception e) {
            try {
                exceptionHandler.handleException(e, this, redisProperties.getEnvironment());
            } catch (RedisException ex) {
                log.error("阿里云Redis集群命令执行异常", ex);
            }
            throw new RedisCommandException.ExecutionException("阿里云Redis集群命令执行失败: " + e.getMessage(), e);
        }
    }

    // 重写关键方法以支持集群模式
    @Override
    public boolean set(String key, String value) {
        if (isClusterMode) {
            return executeClusterCommand(cluster -> {
                cluster.set(key, value);
                return true;
            });
        } else {
            return super.set(key, value);
        }
    }

    @Override
    public String get(String key) {
        if (isClusterMode) {
            return executeClusterCommand(cluster -> cluster.get(key));
        } else {
            return super.get(key);
        }
    }

    @Override
    public boolean del(String key) {
        if (isClusterMode) {
            return executeClusterCommand(cluster -> cluster.del(key) > 0);
        } else {
            return super.del(key);
        }
    }

    // 事务操作（集群模式不支持）
    @Override
    public void multi() {
        if (isClusterMode) {
            throw new RedisCommandException("阿里云Redis集群模式不支持事务操作");
        }
        super.multi();
    }

    @Override
    public void exec() {
        if (isClusterMode) {
            throw new RedisCommandException("阿里云Redis集群模式不支持事务操作");
        }
        super.exec();
    }

    @Override
    public void discard() {
        if (isClusterMode) {
            throw new RedisCommandException("阿里云Redis集群模式不支持事务操作");
        }
        super.discard();
    }

    // 管道操作（集群模式不支持）
    @Override
    public void pipeline() {
        if (isClusterMode) {
            throw new RedisCommandException("阿里云Redis集群模式不支持管道操作");
        }
        super.pipeline();
    }

    @Override
    public void sync() {
        if (isClusterMode) {
            throw new RedisCommandException("阿里云Redis集群模式不支持管道操作");
        }
        super.sync();
    }

    // 连接管理
    @Override
    public boolean ping() {
        if (isClusterMode) {
            try {
                if (jedisCluster != null) {
                    Map<String, ConnectionPool> clusterNodes = jedisCluster.getClusterNodes();
                    if (clusterNodes != null && !clusterNodes.isEmpty()) {
                        ConnectionPool pool = clusterNodes.values().iterator().next();
                        try (Connection conn = pool.getResource()) {
                            return "PONG".equals(conn.ping());
                        }
                    }
                }
                return false;
            } catch (Exception e) {
                log.error("阿里云Redis集群ping失败", e);
                return false;
            }
        } else {
            return super.ping();
        }
    }

    @Override
    public void close() {
        if (jedisCluster != null) {
            try {
                jedisCluster.close();
            } catch (Exception e) {
                log.error("关闭阿里云Redis集群连接失败", e);
            } finally {
                jedisCluster = null;
            }
        }
        super.close();
    }

    @PreDestroy
    public void destroy() {
        close();
        if (connectionFactory != null) {
            connectionFactory.close();
        }
    }
}